//+--------------------------------------------------------------------------------
//| Copyright (c) 2012 - 2013 ### an.vuongngocduy
//| This file is a part of Compact Game Engine (CGE)
//+--------------------------------------------------------------------------------
#ifndef __CGE_MATH_H__
#define __CGE_MATH_H__

#include <math.h>
#include <stdarg.h>
#include "cgeCommons.h"

namespace cge
{
	namespace std
	{
		class Math
		{
		public:
			//! Return absolute value of number
			template<class TArg>
			static TArg Abs(TArg n0);

			//! Return the square root of real number
			static f32 Sqrt(f32 n0);


			//! Return cosine of an angle
			static f32 Cos(f32 angle);


			//! Return sine of an angle
			static f32 Sin(f32 angle);


			//! Return the arc cosine of an angle in radians
			static f32 Acos(f32 n0);


			//! Return maximum of 2 real numbers
			static f32 Max(f32 n0 , f32 n1);


			//! Return maximum of series of real numbers
			static f32 Max(u32 count, ...);


			//! Return minimum of 2 real numbers
			static f32 Min(f32 n0, f32 n1);


			//! Return minimum of series of real numbers
			static f32 Min(u32 count, ...);


			//! Return the floor value of a real number
			static f32 Floor(f32 n0);
		

			//! Return the ceiling value of a real number
			static f32 Ceil(f32 n0);


		public:
			//! Constant PI number
			static const f32 PI;
		};
	}
	
	//! Math class implementation
	namespace std
	{
		//=========================================================================================
		template<class TArg>
		inline TArg Math::Abs(TArg n0)
		{
			return (TArg)abs(n0);
		}

		//=========================================================================================
		inline f32 Math::Sqrt(f32 n0)
		{
			return sqrt(n0);
		}

		//=========================================================================================
		inline f32 Math::Cos(f32 angle)
		{
			return cos(angle);
		}

		
		//=========================================================================================
		inline f32 Math::Sin(f32 angle)
		{
			return sin(angle);
		}

		//=========================================================================================
		inline f32 Math::Acos(f32 n0)
		{
			return acos(n0);
		}

		//=========================================================================================
		inline f32 Math::Max(f32 n0, f32 n1)
		{
			return (n0 > n1) ? n0 : n1;
		}

		//=========================================================================================
		inline f32 Math::Max(u32 count, ...)
		{
			va_list vl;
			va_start(vl, count);
			
			f32 max = va_arg(vl, f32);
			for(u32 i = 1; i < count; i++)
			{
				f32 value = va_arg(vl, f32);
				max = ( value > max ) ? value : max;
			}
			
			va_end(vl);	
			return 0;
		}

		//=========================================================================================
		inline f32 Math::Min(f32 n0, f32 n1)
		{
			return (n0 < n1) ? n0 : n1;
		}

		//=========================================================================================
		inline f32 Math::Min(u32 count, ...)
		{
			va_list vl;
			va_start(vl, count);
			
			f32 max = va_arg(vl, f32);
			for(u32 i = 1; i < count; i++)
			{
				f32 value = va_arg(vl, f32);
				max = ( value < max ) ? value : max;
			}
			
			va_end(vl);	
			return 0;
		}

		//=========================================================================================
		inline f32 Math::Floor(f32 n0)
		{
			return floor(n0);
		}

		//=========================================================================================
		inline f32 Math::Ceil(f32 n0)
		{
			return ceil(n0);
		}

		//=========================================================================================
		#define DET2(_00, _01, _10, _11) ((_00*_11 - _01*_10))
		#define DET3(_00, _01, _02, _10, _11, _12, _20, _21, _22) ((_00*_11*_22 + _01*_12*_20 + _02*_10*_21) - (_02*_11*_20 + _01*_10*_22 + _00*_12*_21))
		
		//=========================================================================================
	}
}


#endif//__CGE_MATH_H__